home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / QuickTime VR / MacOS / QuickDraw™ 3D 1.0.6F4 SDK / Samples / SampleCode / Tumbler and Podium / Tumbler_document.c < prev    next >
Encoding:
Text File  |  1995-11-13  |  25.3 KB  |  878 lines  |  [TEXT/MPS ]

  1. //    Tumbler_document.c
  2. //
  3. //    Document handling routines.
  4. //        
  5. //    Author:        Nick Thompson & Pablo Fernicola, with thanks to the QuickDraw 3D team
  6. //
  7. //    Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
  8. //
  9. //    Modification History:
  10. //
  11. //    11/26/94    nick    clean up, remove old TE references from dragtext, remove
  12. //                        all other dead code.
  13. //                        Modify CloseDocument & CloseAllDocuments to return a Boolean.
  14. //    01/26/95    nick    parameterized NewDocument to take a (possibly null) group
  15. //                        and viewhints.  Factored this routine as it was way too long
  16. //
  17. // to do: store the document reference as a handle in the window's refcon
  18. //
  19.  
  20. #include <Drag.h>
  21. #include <QuickDraw.h>
  22.  
  23.  
  24. #include "Tumbler_globals.h"
  25. #include "Tumbler_prototypes.h"
  26. #include "Tumbler_resources.h"
  27.  
  28. #include "QD3DDrawContext.h"
  29. #include "QD3DCamera.h"
  30. #include "QD3DView.h"
  31. #include "QD3DLight.h"
  32. #include "QD3DGeometry.h"
  33. #include "QD3DSet.h"
  34. #include "QD3DTransform.h"
  35. #include "QD3DShader.h"
  36. #include "QD3DShader.h"
  37. #include "QD3DMath.h"
  38. #include "QD3DIO.h"
  39.  
  40. #include "Tumbler_camera.h"
  41. #include "Tumbler_document.h"
  42. #include "Tumbler_file.h"
  43.  
  44. #include "Tumbler_utility.h"
  45.  
  46. extern pascal OSErr MyTrackingHandler(short message, WindowPtr theWindow,
  47.                                          void *handlerRefCon, DragReference theDrag);
  48.  
  49. extern pascal OSErr MyReceiveDropHandler(WindowPtr theWindow, void *handlerRefCon,
  50.                                          DragReference theDrag);
  51.  
  52. //----------------------------------------------------------------------
  53. TQ3Status TumblerDocument_NewLights( DocumentPtr theDocument ) 
  54. {
  55.     TQ3GroupObject            lightGroup;
  56.     TQ3LightObject            light;
  57.     TQ3PointLightData        pointData;
  58.     TQ3LightData                ambientData;
  59.     
  60.     lightGroup = Q3LightGroup_New();
  61.  
  62.     pointData.lightData.isOn        = kQ3True;
  63.     pointData.lightData.brightness    = 0.950;
  64.     pointData.lightData.color.r     = 1.0;
  65.     pointData.lightData.color.g     = 1.0;
  66.     pointData.lightData.color.b     = 1.0;
  67.     pointData.location.x            = -10.0;
  68.     pointData.location.y            = 10.0;
  69.     pointData.location.z            = 30.0;
  70.     pointData.castsShadows            = kQ3False;
  71.     pointData.attenuation            = kQ3AttenuationTypeNone;
  72.     
  73.     light = Q3PointLight_New(&pointData);
  74.     Q3Group_AddObject(lightGroup, light);
  75.     Q3Object_Dispose(light);
  76.  
  77.     ambientData.isOn        = kQ3True;
  78.     ambientData.brightness    = 0.70;
  79.     ambientData.color.r     = 0.4;
  80.     ambientData.color.g     = 0.4;
  81.     ambientData.color.b     = 0.4;
  82.     
  83.     light = Q3AmbientLight_New(&ambientData);
  84.     Q3Group_AddObject(lightGroup, light);
  85.     Q3Object_Dispose(light);
  86.  
  87.     pointData.lightData.isOn        = kQ3False;
  88.     pointData.lightData.brightness    = 0.80;
  89.     pointData.lightData.color.r     = 1.0;
  90.     pointData.lightData.color.g     = 0.0;
  91.     pointData.lightData.color.b     = 0.0;
  92.     pointData.location.x            = -10.0;
  93.     pointData.location.y            = 0.0;
  94.     pointData.location.z            = 5.0;
  95.     pointData.castsShadows            = kQ3False;
  96.     pointData.attenuation            = kQ3AttenuationTypeInverseDistance;
  97.     
  98.     light = Q3PointLight_New(&pointData);
  99.     Q3Group_AddObject(lightGroup, light);
  100.     Q3Object_Dispose(light);
  101.  
  102.     pointData.lightData.isOn        = kQ3False;
  103.     pointData.lightData.brightness    = 0.80;
  104.     pointData.lightData.color.r     = 0.0;
  105.     pointData.lightData.color.g     = 1.0;
  106.     pointData.lightData.color.b     = 0.0;
  107.     pointData.location.x            = 10.0;
  108.     pointData.location.y            = 0.0;
  109.     pointData.location.z            = 5.0;
  110.     pointData.castsShadows            = kQ3False;
  111.     pointData.attenuation            = kQ3AttenuationTypeInverseDistance;
  112.     
  113.     light = Q3PointLight_New(&pointData);
  114.     Q3Group_AddObject(lightGroup, light);
  115.     Q3Object_Dispose(light);
  116.  
  117.  
  118.     pointData.lightData.isOn        = kQ3False;
  119.     pointData.lightData.brightness    = 0.80;
  120.     pointData.lightData.color.r     = 0.0;
  121.     pointData.lightData.color.g     = 0.0;
  122.     pointData.lightData.color.b     = 1.0;
  123.     pointData.location.x            = 10.0;
  124.     pointData.location.y            = 0.0;
  125.     pointData.location.z            = 5.0;
  126.     pointData.castsShadows            = kQ3False;
  127.     pointData.attenuation            = kQ3AttenuationTypeInverseDistance;
  128.     
  129.     light = Q3PointLight_New(&pointData);
  130.     Q3Group_AddObject(lightGroup, light);
  131.     Q3Object_Dispose(light);
  132.  
  133.     Q3View_SetLightGroup(theDocument->theView, lightGroup);
  134.     Q3Object_Dispose(lightGroup);
  135. //        
  136.     {
  137. #if defined(ESCHER_VER_15) && ESCHER_VER_15
  138.  
  139.         TQ3ColorRGB                        ellipsoidColor;
  140.         TQ3EllipsoidData                    ellipsoidData;
  141.         TQ3GeometryObject                ellipsoid;
  142.  
  143.  
  144.         TQ3RotateTransformData            rotateData;
  145.         
  146.         theDocument->dynamicLights = Q3DisplayGroup_New();
  147.         
  148.         ellipsoidData.origin.x = -10.0;
  149.         ellipsoidData.origin.y = 0.0;
  150.         ellipsoidData.origin.z = 5.0;
  151.         
  152.         ellipsoidData.orientation.x = 0.0;
  153.         ellipsoidData.orientation.y = 1.0;
  154.         ellipsoidData.orientation.z = 0.0;
  155.         
  156.         ellipsoidData.majorRadius.x = 0.0;
  157.         ellipsoidData.majorRadius.y = 0.0;
  158.         ellipsoidData.majorRadius.z = 1.0;
  159.         
  160.         ellipsoidData.minorRadius.x = 1.0;
  161.         ellipsoidData.minorRadius.y = 0.0;
  162.         ellipsoidData.minorRadius.z = 0.0;
  163.  
  164.         ellipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  165.         
  166.         /* Red light ball */
  167.         ellipsoidColor.r = 1.0;
  168.         ellipsoidColor.g = 0.0;
  169.         ellipsoidColor.b = 0.0;
  170.         
  171.         Q3AttributeSet_Add( ellipsoidData.ellipsoidAttributeSet, 
  172.         kQ3AttributeTypeDiffuseColor, &ellipsoidColor);
  173.  
  174.         Q3AttributeSet_Add(ellipsoidData.ellipsoidAttributeSet, 
  175.         kQ3AttributeTypeSpecularColor, &ellipsoidColor);
  176.     
  177.         ellipsoid = Q3Ellipsoid_New(&ellipsoidData);
  178.         Q3Object_Dispose(ellipsoidData.ellipsoidAttributeSet);
  179.         theDocument->light1 = Q3OrderedDisplayGroup_New();
  180.         Q3Group_AddObject(theDocument->light1, ellipsoid);
  181.         Q3Object_Dispose(ellipsoid);
  182.  
  183.         rotateData.axis = kQ3AxisY;
  184.         rotateData.radians = 0.0;
  185.         
  186.         theDocument->lightXform1 = Q3RotateTransform_New(&rotateData);
  187.         Q3Group_AddObject(theDocument->light1, theDocument->lightXform1);
  188.         
  189.         Q3Group_AddObject(theDocument->dynamicLights, theDocument->light1);
  190.         
  191.         /* Green light ball */
  192.         ellipsoidData.origin.x = 10.0;
  193.         ellipsoidData.origin.y = 0.0;
  194.         ellipsoidData.origin.z = 5.0;
  195.  
  196.         ellipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  197.         
  198.         ellipsoidColor.r = 0.0;
  199.         ellipsoidColor.g = 1.0;
  200.         ellipsoidColor.b = 0.0;
  201.         Q3AttributeSet_Add( ellipsoidData.ellipsoidAttributeSet, 
  202.         kQ3AttributeTypeDiffuseColor, (const void *) &ellipsoidColor);
  203.  
  204.         Q3AttributeSet_Add(ellipsoidData.ellipsoidAttributeSet, 
  205.         kQ3AttributeTypeSpecularColor, &ellipsoidColor);
  206.     
  207.         ellipsoid = Q3Ellipsoid_New(&ellipsoidData);
  208.         Q3Object_Dispose(ellipsoidData.ellipsoidAttributeSet);
  209.         theDocument->light2 = Q3OrderedDisplayGroup_New();
  210.         Q3Group_AddObject(theDocument->light2, ellipsoid);
  211.         Q3Object_Dispose(ellipsoid);                            
  212.  
  213.         theDocument->lightXform2 = Q3RotateTransform_New(&rotateData);
  214.         Q3Group_AddObject(theDocument->light2, theDocument->lightXform2);
  215.  
  216.         Q3Group_AddObject(theDocument->dynamicLights, theDocument->light2);
  217.         
  218.         /* Blue light ball */
  219.         ellipsoidData.origin.x = 5.0;
  220.         ellipsoidData.origin.y = 0.0;
  221.         ellipsoidData.origin.z = 10.0;
  222.  
  223.         ellipsoidData.ellipsoidAttributeSet = Q3AttributeSet_New();
  224.         
  225.         ellipsoidColor.r = 0.0;
  226.         ellipsoidColor.g = 0.0;
  227.         ellipsoidColor.b = 1.0;
  228.         Q3AttributeSet_Add( ellipsoidData.ellipsoidAttributeSet, 
  229.         kQ3AttributeTypeDiffuseColor, (const void *) &ellipsoidColor);
  230.  
  231.         Q3AttributeSet_Add(ellipsoidData.ellipsoidAttributeSet, 
  232.         kQ3AttributeTypeSpecularColor, &ellipsoidColor);
  233.     
  234.         ellipsoid = Q3Ellipsoid_New(&ellipsoidData);
  235.         Q3Object_Dispose(ellipsoidData.ellipsoidAttributeSet);
  236.         theDocument->light3 = Q3OrderedDisplayGroup_New();
  237.         Q3Group_AddObject(theDocument->light3, ellipsoid);
  238.         Q3Object_Dispose(ellipsoid);                            
  239.  
  240.         rotateData.axis = kQ3AxisX;
  241.         theDocument->lightXform3 = Q3RotateTransform_New(&rotateData);
  242.         Q3Group_AddObject(theDocument->light3, theDocument->lightXform3);
  243.  
  244.         Q3Group_AddObject(theDocument->dynamicLights, theDocument->light3);
  245. #endif        
  246.     }
  247.     
  248.     theDocument->animateLights = kQ3False;
  249.  
  250.     return(kQ3Success);
  251. }
  252.  
  253. //-----------------------------------------------------------------------------------
  254. TQ3CameraObject TumblerDocument_NewCamera(WindowPtr theWindow)
  255. {
  256.     TQ3ViewAngleAspectCameraData    perspectiveData;
  257.     TQ3CameraObject                camera;
  258.     
  259.     TQ3Point3D                     from     = { 0.0, 0.0, 30.0 };
  260.     TQ3Point3D                     to         = { 0.0, 0.0, 0.0 };
  261.     TQ3Vector3D                     up         = { 0.0, 1.0, 0.0 };
  262.  
  263.     float                         fieldOfView = .52359333333;
  264.     float                         hither         =  0.001;
  265.     float                         yon         =  1000;
  266.     
  267.     TQ3Status                    returnVal = kQ3Failure ;
  268.  
  269.  
  270.     perspectiveData.cameraData.placement.cameraLocation     = from;
  271.     perspectiveData.cameraData.placement.pointOfInterest     = to;
  272.     perspectiveData.cameraData.placement.upVector             = up;
  273.  
  274.     perspectiveData.cameraData.range.hither    = hither;
  275.     perspectiveData.cameraData.range.yon     = yon;
  276.  
  277.     perspectiveData.cameraData.viewPort.origin.x = -1.0;
  278.     perspectiveData.cameraData.viewPort.origin.y = 1.0;
  279.     perspectiveData.cameraData.viewPort.width = 2.0;
  280.     perspectiveData.cameraData.viewPort.height = 2.0;
  281.     
  282.     perspectiveData.fov                = fieldOfView;
  283.     perspectiveData.aspectRatioXToY    =
  284.         (float) (theWindow->portRect.right - theWindow->portRect.left) / 
  285.         (float) (theWindow->portRect.bottom - theWindow->portRect.top);
  286.         
  287.     camera = Q3ViewAngleAspectCamera_New(&perspectiveData);
  288.  
  289.     return camera ;
  290. }
  291.  
  292. //--------------------------------------------------------------------------------
  293.  
  294. #ifdef PODIUM_APP
  295.  
  296. TQ3DrawContextObject TumblerDocument_NewPixmapDrawContext( DocumentPtr theDocument )
  297. {
  298.     TQ3PixmapDrawContextData     myDrawContextData;
  299.     TQ3ColorARGB                clearColor = {1.0, 1.0, 1.0, 1.0} ;
  300.     TQ3DrawContextObject        myDrawContext ;
  301.     GWorldPtr                     theGWorld ;
  302.     PixMapHandle                hPixMap ;
  303.     Rect                        srcRect ;
  304.     
  305.     theGWorld = theDocument->geometriesOffscreen ;
  306.     
  307.     //    Fill in draw context data.
  308.     myDrawContextData.drawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  309.     myDrawContextData.drawContextData.clearImageColor  = clearColor;
  310.  
  311.     myDrawContextData.drawContextData.paneState = kQ3False;
  312.     myDrawContextData.drawContextData.maskState = kQ3False;
  313.     
  314.     myDrawContextData.drawContextData.doubleBufferState = kQ3False;
  315.     
  316.     hPixMap = GetGWorldPixMap(theGWorld);
  317.     LockPixels(hPixMap);
  318.  
  319.     srcRect = theGWorld->portRect;
  320.  
  321.     myDrawContextData.pixmap.width = srcRect.right  - srcRect.left;
  322.     myDrawContextData.pixmap.height= srcRect.bottom - srcRect.top;
  323.     
  324.     myDrawContextData.pixmap.rowBytes = (**hPixMap).rowBytes & 0x7FFF;
  325.     myDrawContextData.pixmap.pixelType = kQ3PixelTypeRGB32;
  326.     myDrawContextData.pixmap.pixelSize = 32;
  327.  
  328.     myDrawContextData.pixmap.bitOrder  = kQ3EndianBig;
  329.     myDrawContextData.pixmap.byteOrder = kQ3EndianBig;
  330.     
  331.     myDrawContextData.pixmap.image        = (**hPixMap).baseAddr;
  332.     
  333.     return Q3PixmapDrawContext_New(&myDrawContextData);
  334. }
  335.  
  336. #endif
  337.  
  338. //--------------------------------------------------------------------------------
  339.  
  340. TQ3DrawContextObject TumblerDocument_NewDrawContext( WindowPtr theWindow )
  341. {
  342.     TQ3DrawContextData        myDrawContextData;
  343.     TQ3MacDrawContextData    myMacDrawContextData;
  344.     TQ3DrawContextObject    myDrawContext ;
  345.     TQ3ColorARGB            clearColor = {1.0, kTumblerDefaultClearColor, kTumblerDefaultClearColor, kTumblerDefaultClearColor};    // lt gray
  346.  
  347.     //    Fill in draw context data.
  348.     myDrawContextData.clearImageMethod = kQ3ClearMethodWithColor;
  349.     myDrawContextData.clearImageColor = clearColor;
  350.     myDrawContextData.pane.min.x = (theWindow->portRect).left;
  351.     myDrawContextData.pane.max.x = (theWindow->portRect).right; 
  352.     myDrawContextData.pane.min.y = (theWindow->portRect).top;
  353.     myDrawContextData.pane.max.y = (theWindow->portRect).bottom;
  354.     myDrawContextData.paneState = kQ3False;
  355.     myDrawContextData.maskState = kQ3False;
  356.     myDrawContextData.doubleBufferState = kQ3True;
  357.  
  358.     myMacDrawContextData.drawContextData = myDrawContextData;
  359.     
  360.     myMacDrawContextData.library = kQ3Mac2DLibraryNone;
  361.     myMacDrawContextData.window = (CWindowPtr) theWindow;
  362.     myMacDrawContextData.grafPort = nil;
  363.     myMacDrawContextData.viewPort = nil;
  364.     
  365.     //    Create draw context and return it, if it’s nil the caller must handle
  366.     myDrawContext = Q3MacDrawContext_New(&myMacDrawContextData) ;
  367.  
  368.     return myDrawContext ;
  369. }
  370.  
  371.  
  372. //--------------------------------------------------------------------------------
  373. TQ3Status    TumblerDocument_UpdateView( DocumentPtr theDocument, TQ3SharedObject viewHints )
  374. {
  375.     TQ3Object                tempObject;
  376.     TQ3CameraObject            camera ;
  377.     
  378.     if( theDocument->theView == NULL)
  379.         return kQ3Failure ;
  380.         
  381.     TumblerDocument_NewLights( theDocument ) ;
  382.  
  383.     if( viewHints == NULL ) {
  384.         
  385.         // if we were called with null viewhints, then just set up
  386.         // sensible defaults for the current document
  387.  
  388.         camera = TumblerDocument_NewCamera( theDocument->theWindow ) ;
  389.         if( camera != NULL ) {
  390.             Q3View_SetCamera(theDocument->theView, camera );
  391.             Q3Object_Dispose(camera);
  392.         }
  393.         else 
  394.             return kQ3Failure ;
  395.         
  396.         Q3View_SetRendererByType(theDocument->theView, kQ3RendererTypeInteractive);
  397.     }
  398.     else {
  399.     
  400.         // we think we have valid viewhints, so attempt to 
  401.         // get the information we need from the viewhints 
  402.         // passed in, where we dont have an item, then make
  403.         // a sensible default.
  404.         
  405.         // renderer information
  406.         Q3ViewHints_GetRenderer(viewHints, &tempObject);
  407. #ifndef PODIUM_APP
  408.         if (tempObject != NULL)
  409.         {
  410.             Q3View_SetRenderer(theDocument->theView, tempObject);
  411.             Q3Object_Dispose(tempObject);
  412.         }
  413.         else
  414.             Q3View_SetRendererByType(theDocument->theView, kQ3RendererTypeWireFrame);
  415. #else
  416.             Q3View_SetRendererByType(theDocument->theView, kQ3RendererTypeInteractive);
  417. #endif
  418.     
  419.         // camera information
  420.         tempObject = NULL ;
  421. //        Q3ViewHints_GetCamera(viewHints, &tempObject);
  422.         if (tempObject != NULL) {
  423.             Q3View_SetCamera(theDocument->theView, tempObject);
  424.             Q3Object_Dispose(tempObject);
  425.         }    
  426.         else {
  427.             camera = TumblerDocument_NewCamera( theDocument->theWindow ) ;
  428.             if( camera != NULL ) {
  429.                 Q3View_SetCamera(theDocument->theView, camera );
  430.                 Q3Object_Dispose(camera);
  431.             }
  432.             else 
  433.                 return kQ3Failure ;
  434. #ifndef PODIUM_APP                    
  435.             AdjustCamera(theDocument,
  436.                                 theDocument->theWindow->portRect.right - theDocument->theWindow->portRect.left,
  437.                                 theDocument->theWindow->portRect.bottom - theDocument->theWindow->portRect.top);    
  438.  
  439. #else
  440.             AdjustCamera(theDocument,
  441.                                 theDocument->geometriesOffscreen->portRect.right - theDocument->geometriesOffscreen->portRect.left,
  442.                                 theDocument->geometriesOffscreen->portRect.bottom - theDocument->geometriesOffscreen->portRect.top);    
  443. #endif
  444.         }        
  445.         
  446.         // light information
  447.         Q3ViewHints_GetLightGroup(viewHints, &tempObject);
  448.         if (tempObject != NULL) {
  449.             Q3View_SetLightGroup(theDocument->theView, tempObject);
  450.             Q3Object_Dispose(tempObject);
  451.         }            
  452.         else {
  453.             TumblerDocument_NewLights( theDocument ) ;
  454.         }
  455.     
  456.     }
  457.     
  458.     // replace the existing view hints
  459.     if( theDocument->viewHints ) {
  460.         Q3Object_Dispose(theDocument->viewHints);
  461.     }
  462.     theDocument->viewHints = Q3ViewHints_New(theDocument->theView);
  463.     
  464.     SetPort( (GrafPtr)theDocument->theWindow) ;
  465.     InvalRect( &theDocument->theWindow->portRect ) ;
  466.     
  467.     return kQ3Success ;
  468. }
  469.  
  470.  
  471.  
  472.  
  473.  
  474. //--------------------------------------------------------------------------------
  475. //    NewDocument is called when a new document window is needed. Creation of
  476. //    document data structures is handled here.
  477. //
  478.  
  479. DocumentPtr NewDocument( TQ3SharedObject viewHints, TQ3GroupObject group )
  480. {
  481.     DocumentPtr theDocument;
  482.     WindowPtr        theWindow;
  483.     Rect            theRect = { 0, 0, 16, 16 };
  484.     Point            thePoint;
  485.     TQ3Param2D        uvValues = {-1.0, -1.0};
  486.     
  487.     TQ3DrawContextObject        theDrawContext ;
  488.     TQ3CameraObject            camera ;
  489.     TQ3AttributeSet            viewSet;
  490.     
  491.     if (gDocumentCount == MaxDocumentCount)
  492.         return( (DocumentPtr )nil );
  493.         
  494.         
  495.     // make sure the pointer is initialised to nil, because we rely on
  496.     // the fields being non nil in order to dispose of the correctly.
  497.     theDocument = gDocumentList[gDocumentCount++] =
  498.                             (DocumentPtr )NewPtrClear(sizeof(DocumentRecord));
  499.  
  500. #ifdef PODIUM_APP
  501.     {
  502.         // for podium set up two GWorlds, on for the bg picture, one for the 
  503.         // pixmap draw context that we'll draw the geomentries into
  504.         
  505.         Rect        defaultGeometryRect = { 0, 0, 200, 200 } ;
  506.         GWorldPtr    savedGWorld ;
  507.         GDHandle    savedGDH ;
  508.         
  509.         GetGWorld( &savedGWorld, &savedGDH ) ;
  510.         
  511.         if( NewGWorld(&theDocument->bgOffscreen, 16, &defaultGeometryRect, nil, nil, 0L ) != noErr ) {
  512.             CloseDocument( theDocument ) ;
  513.             return NULL ;
  514.         }
  515.         SetGWorld( theDocument->bgOffscreen, nil ) ;
  516.         EraseRect( &theDocument->bgOffscreen->portRect ) ;
  517.         
  518.         if( NewGWorld(&theDocument->screenBuffer, 16, &defaultGeometryRect, nil, nil, 0L ) != noErr ) {
  519.             CloseDocument( theDocument ) ;
  520.             return NULL ;
  521.         }
  522.         SetGWorld( theDocument->screenBuffer, nil ) ;
  523.         EraseRect( &theDocument->screenBuffer->portRect ) ;
  524.         
  525.         if( NewGWorld(&theDocument->geometriesOffscreen, 32, &defaultGeometryRect, nil, nil, 0L ) != noErr ) {
  526.             CloseDocument( theDocument ) ;
  527.             return NULL ;
  528.         }
  529.         SetGWorld( theDocument->geometriesOffscreen, nil ) ;
  530.         EraseRect( &theDocument->geometriesOffscreen->portRect ) ;
  531.         theDocument->dropArea = defaultGeometryRect ;
  532.         
  533.         // create a 1-bit GW for the mask
  534. //        if( NewGWorld( &theDocument->maskOffscreen, 1, &theDocument->geometriesOffscreen->portRect, nil, nil, 0L)  != noErr ) {
  535. //            CloseDocument( theDocument ) ;
  536. //            return NULL ;
  537. //        }
  538. //        SetGWorld( theDocument->maskOffscreen, nil ) ;
  539. //        EraseRect( &theDocument->maskOffscreen->portRect ) ;
  540.         
  541.         SetGWorld( savedGWorld, savedGDH ) ;
  542.         
  543.         theDocument->currentInterpolation = kQ3InterpolationStyleVertex;
  544.     }
  545. #endif
  546.  
  547.  
  548.     theWindow = GetNewCWindow(WindowTemplateID, 0L, (WindowPtr) -1L);
  549.  
  550.     if (theWindow == nil)
  551.         return( (DocumentPtr )nil );
  552.  
  553.     
  554.     theDocument->theWindow = theWindow ;
  555.                     
  556.     SetWRefCon(theWindow, (long)theDocument ) ;
  557.  
  558.     SetPort(theWindow);
  559.  
  560. #ifndef PODIUM_APP
  561.     // only want to set the bg color up for Tumbler
  562.     {
  563.         RGBColor color = { 0xFFFF, 0xFFFF, 0xFFFF};
  564.         theDocument->clearColor.r = kTumblerDefaultClearColor ;
  565.         theDocument->clearColor.g = kTumblerDefaultClearColor ;
  566.         theDocument->clearColor.b = kTumblerDefaultClearColor ;
  567.         
  568.         color.red *= theDocument->clearColor.r;
  569.         color.green *= theDocument->clearColor.r;
  570.         color.blue *= theDocument->clearColor.r;
  571.         
  572.         RGBBackColor(&color);
  573.         EraseRect(&theWindow->portRect);
  574.         
  575.         color.blue = color.green = color.red  =  0xFFFF;
  576.         RGBBackColor(&color);
  577.     }
  578. #endif
  579.  
  580.     thePoint = *((Point *) (&theWindow->portRect.top));
  581.     LocalToGlobal(&thePoint);
  582.     if (thePoint.h < 10) {
  583.         MoveWindow(theWindow, InitialH, InitialV, false);
  584.     }
  585.  
  586.     theDocument->fRefNum = 0;
  587.  
  588.     // zero out the file spec
  589.     theDocument->theFileSpec.vRefNum = 0 ;
  590.     theDocument->theFileSpec.parID = 0 ;
  591.     theDocument->theFileSpec.name[0] = '\0' ;
  592.     
  593.     theDocument->dirty = false;
  594.     
  595.     // set up the draw context, camera and lights
  596. #ifndef PODIUM_APP
  597.     theDrawContext = TumblerDocument_NewDrawContext( theWindow ) ;
  598. #else
  599.     theDrawContext = TumblerDocument_NewPixmapDrawContext( theDocument ) ;
  600.  
  601. #endif
  602.     if( theDrawContext != NULL ) {
  603.         TQ3ColorRGB            clearColor = {1.0, 1.0, 1.0};
  604.  
  605.         theDocument->theView = Q3View_New();
  606.     
  607.         Q3View_GetDefaultAttributeSet(theDocument->theView, &viewSet);
  608.         Q3AttributeSet_Add(viewSet, 
  609.             kQ3AttributeTypeSpecularColor, &clearColor);
  610.         Q3AttributeSet_Add(viewSet, 
  611.             kQ3AttributeTypeSurfaceUV, &clearColor);
  612.         Q3AttributeSet_Add(viewSet, 
  613.             kQ3AttributeTypeShadingUV, &clearColor);
  614.         Q3Object_Dispose(viewSet);
  615.         
  616.         Q3View_SetDrawContext(theDocument->theView, theDrawContext);
  617.         Q3Object_Dispose(theDrawContext);
  618.     }
  619.     else
  620.         return NULL ;
  621.  
  622.                             
  623.     InstallTrackingHandler(NewDragTrackingHandlerProc(MyTrackingHandler), theWindow, (void *) theDocument);
  624.     InstallReceiveHandler(NewDragReceiveHandlerProc(MyReceiveDropHandler), theWindow, (void *) theDocument);
  625.  
  626.     Q3Matrix4x4_SetIdentity(&theDocument->modelRotation);
  627.     
  628.     theDocument->animateModel = kQ3False;
  629.     theDocument->light = kQ3False;
  630.     theDocument->shaded = kQ3False;
  631.     theDocument->documentGroup = nil;
  632.     
  633. #ifndef PODIUM_APP
  634.     theDocument->currentInterpolation = kQ3InterpolationStyleNone;
  635. #endif
  636.  
  637.     theDocument->backfacingStyle = Q3BackfacingStyle_New(kQ3BackfacingStyleRemove ) ;
  638.     theDocument->viewHints = Q3ViewHints_New(theDocument->theView);\
  639.     theDocument->illuminationShader = Q3PhongIllumination_New();
  640.  
  641.  
  642.     return(theDocument);
  643. }
  644.  
  645.  
  646. //----------------------------------------------------------------------------------
  647. //    CloseDocument is called when a document window is being closed. Storage
  648. //    of the document file and disposal of document data structures is handled
  649. //    here.
  650.  
  651. Boolean CloseDocument( DocumentPtr theDocument )
  652.  
  653. {    short            index, response;
  654.     Str255            theName, theVerb;
  655.     Boolean            couldCloseIt = false ;
  656.  
  657.     index = 0;
  658.     
  659.     while ((gDocumentList[index] != theDocument) && (index < MaxDocumentCount))
  660.         index++;
  661.  
  662.     if (gDocumentList[index] == theDocument) {
  663.  
  664.         if (theDocument->dirty) {
  665.             GetWTitle(theDocument->theWindow, theName);
  666.             GetIndString(theVerb, FileStringsID, (gQuitting) ? slQuittingIndex : slClosingIndex);
  667.             ParamText( (ConstStr255Param)&theName, (ConstStr255Param) &theVerb, (ConstStr255Param) "", (ConstStr255Param) "");
  668.             SetCursor(&qd.arrow);
  669.             
  670.             // check with the user - do they want to save this thing
  671.             response = Alert(idSaveChangesALRT, 0L);
  672.  
  673.             if (response == 1) {            // Save
  674.             
  675.                 // check to see that we were able to save the 
  676.                 // document as requested to by the user
  677.                 
  678.                 if (!DidSaveDocument(theDocument)) {
  679.                 
  680.                     // signal that we are not quitting (if we were actually trying)
  681.                     gQuitting = false;
  682.                     
  683.                     // signal that we couldn't save this document
  684.                     couldCloseIt = false ;
  685.                     
  686.                     return couldCloseIt;
  687.                 }
  688.                 
  689.             } else if (response == 3) {        /* Don't Save */
  690.                 ;
  691.             } else {                        /* Cancel */
  692.                 gQuitting = false ;
  693.                 
  694.                 // signal that we didn't actually want to close this document
  695.                 couldCloseIt = false ;
  696.                 
  697.                 return couldCloseIt;
  698.             }
  699.         }
  700.         
  701.         // if we are here we can assume the document has been saved (if required) and 
  702.         // that we can junk all of the data structures associated with the document
  703.  
  704.         // if it has a file associated, close it
  705.         if (theDocument->fRefNum) {
  706.             FSClose(theDocument->fRefNum);
  707.         }
  708.  
  709.         // remove our drag manager handlers
  710.         RemoveTrackingHandler(NewDragTrackingHandlerProc(MyTrackingHandler), theDocument->theWindow);
  711.         RemoveReceiveHandler(NewDragReceiveHandlerProc(MyReceiveDropHandler), theDocument->theWindow);
  712.  
  713.         // and we can dispose of the window
  714.         if(theDocument->theWindow)
  715.             DisposeWindow(theDocument->theWindow);
  716.  
  717.         // close any holes left in the array we 
  718.         // have for storing our document objects
  719.         while (index < MaxDocumentCount) {
  720.             gDocumentList[index] = gDocumentList[index + 1];
  721.             index++;
  722.         }
  723.  
  724.         // dispose of our QuickDraw 3d view object
  725.         if(theDocument->theView)
  726.             Q3Object_Dispose(theDocument->theView);
  727.  
  728.         if(theDocument->viewHints)
  729.             Q3Object_Dispose(theDocument->viewHints);
  730.  
  731.         // if we have a group associated with the document, then delete that
  732.         if(theDocument->documentGroup)
  733.             Q3Object_Dispose(theDocument->documentGroup);
  734.  
  735.         // dispose of the lights we set up for this document
  736.         if(theDocument->dynamicLights)
  737.             Q3Object_Dispose(theDocument->dynamicLights);
  738.  
  739.         if(theDocument->light1) {
  740.             Q3Object_Dispose(theDocument->light1);
  741.             Q3Object_Dispose(theDocument->lightXform1);
  742.         }
  743.         
  744.         if(theDocument->light2) {
  745.             Q3Object_Dispose(theDocument->light2);
  746.             Q3Object_Dispose(theDocument->lightXform2);
  747.         }
  748.         
  749.         if(theDocument->light3) {
  750.             Q3Object_Dispose(theDocument->light3);
  751.             Q3Object_Dispose(theDocument->lightXform3);
  752.         }
  753.  
  754.         if(theDocument->backfacingStyle) {
  755.             Q3Object_Dispose(theDocument->backfacingStyle);
  756.         }
  757.  
  758.         if(theDocument->illuminationShader) {
  759.             Q3Object_Dispose(theDocument->illuminationShader);
  760.         }
  761.  
  762. #ifdef PODIUM_APP
  763.  
  764.         if(theDocument->bgOffscreen != nil ) {
  765.             DisposeGWorld(theDocument->bgOffscreen) ;
  766.         }
  767.         
  768.         if(theDocument->screenBuffer != nil ) {
  769.             DisposeGWorld(theDocument->screenBuffer) ;
  770.         }
  771.         
  772.         if(theDocument->geometriesOffscreen != nil ) {
  773.             DisposeGWorld(theDocument->geometriesOffscreen) ;
  774.         }
  775.         
  776. //        if(theDocument->maskOffscreen != nil ) {
  777. //            DisposeGWorld(theDocument->maskOffscreen) ;
  778. //        }
  779.         
  780. #endif
  781.  
  782.         // finally dispose of the storage used for the document and 
  783.         // decrement the document count
  784.         if( theDocument != nil )
  785.             DisposePtr((Ptr) theDocument);
  786.         gDocumentCount--;
  787.         
  788.         // signal that we closed this document
  789.         couldCloseIt = true ;
  790.         return couldCloseIt;
  791.         
  792.     }
  793.  
  794.     // signal that we could't actually close this document
  795.     couldCloseIt = false ;
  796.     return couldCloseIt;
  797. }
  798.  
  799.  
  800. //----------------------------------------------------------------------------------
  801. //    Closes all document windows.
  802. //
  803.  
  804. Boolean CloseAllDocuments( void )
  805. {
  806.     short    index ;
  807.     
  808.     for( index = gDocumentCount - 1; index >= 0; index-- ) {
  809.         if(CloseDocument(gDocumentList[ index ]) == false)
  810.             return false;
  811.     }
  812.     return true ;
  813. }
  814.  
  815.  
  816.  
  817. //----------------------------------------------------------------------------------
  818. //    DoActivateDocument is called when an event is received that reports that
  819. //    a document window is being either activated or deactivated.
  820.  
  821. void DoActivateDocument(DocumentPtr theDocument, short activate)
  822. {
  823.     if (theDocument) {
  824.         if (activate) {
  825.         
  826.             // do whatever you'd like to do for a activate event
  827. #ifdef PODIUM_APP            
  828.             void FixGrayRgnAfterContextSwitch( void ) ;
  829.             FixGrayRgnAfterContextSwitch();
  830. #endif            
  831.             
  832.             LoadScrap() ;
  833.  
  834.         } else {
  835.         
  836.             // do whatever you'd like to do for a deactivate event
  837.             UnloadScrap() ;
  838.         }
  839.     }
  840. }
  841.  
  842.  
  843. //----------------------------------------------------------------------------------
  844. //    If the given WindowPtr is a pointer to a document window, this function
  845. //    returns a pointer to a document data structure. If the window is not
  846. //    a document window, the function returns nil.
  847.  
  848. DocumentPtr GetDocumentFromWindow(WindowPtr theWindow)
  849. {
  850.     short        index = 0;
  851.     DocumentPtr theDocument;
  852.  
  853.     if( theWindow == nil )
  854.         return((DocumentPtr ) 0L);
  855.  
  856.     theDocument = (DocumentPtr ) (((WindowPeek) theWindow)->refCon);
  857.  
  858.     while ((gDocumentList[index] != theDocument) && (index < gDocumentCount))
  859.         index++;
  860.  
  861.     if (gDocumentList[index] == theDocument)
  862.         return(theDocument);
  863.     else
  864.         return((DocumentPtr ) 0L);
  865. }
  866.  
  867.  
  868.  
  869. TQ3Status InitializeGroup(TQ3GroupObject group)
  870. {
  871.     TQ3ShaderObject    illuminationShader = Q3PhongIllumination_New();
  872.  
  873.     Q3Group_AddObject(group, illuminationShader);
  874.     Q3Object_Dispose(illuminationShader);
  875.     return(kQ3Success);
  876. }
  877.  
  878.